home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 2000 #4
/
Amiga Plus CD - 2000 - No. 4.iso
/
PowerPC
/
Games
/
Battalion
/
source
/
net.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-12-23
|
33KB
|
1,054 lines
/****************************************************************/
/* code copyright 1995-1996 Andrew Johnson - ALL RIGHTS RESERVED*/
/* ajohnson@eecs.uic.edu */
/* */
/* Electronic Visualization Lab (M/C 154) */
/* University of Illinois at Chicago */
/* 851 South Morgan St. Room 1120 SEO */
/* Chicago, IL 60607-7053 */
/* */
/* (312) 996-3002 (312) 413-7585 FAX */
/***********************************************************************/
/* net.c v 1.3 */
/* network routines for battalion */
/***********************************************************************/
/* the network coding is pretty much alpha-stage stuff. It seems
* to generally work though the monster positions are slightly off
* in the remote versions making it hard to hit the other person.
*
* the vapour also has a problem getting kills on the other monsters
*
* ocassionally wehn switching from demo to game mode the screen goes
* black and everything stops
*/
#include "battalion.h"
/*****************/
/* network stuff */
/*****************/
#ifdef AMIGAVERSION
struct Library *SocketBase = NULL; /* bsdsocket.library */
#define SOCKETVERSION 4 /* required version */
static long ioctl_true = 1;
#endif
struct sockaddr_in serv_addr;
struct sockaddr_in clients[MAXCLIENTS];
struct sockaddr_in cli_addr;
long clientsFrom[MAXCLIENTS];
int lastClientMonsterUpdate[MAXCLIENTS];
time_t clientsAlive[MAXCLIENTS];
time_t lastRecvTime;
time_t lastNotDeadYetTime;
int lastMonsterUpdate;
int numClients;
int sockfd;
int portNumber;
int connected;
int waitCounter = 0;
int beamOnSinceLast = 0;
int tankModulator = 0;
char hostAddr[40];
extern float globalxshift;
extern float globalzshift;
extern struct targetInfo * targets;
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
void turnBeamOnSinceLast()
{
beamOnSinceLast = 1;
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
void setUnconnected()
{
connected = 0;
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
void setPortNumber(int val)
{
portNumber = val;
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
void setHostAddr(char * val)
{
strcpy(hostAddr, val);
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
int HostnameToIP(char *hostname, char *hostIP)
{
struct hostent* host;
host = gethostbyname(hostname);
if (host)
{
sprintf(hostIP,"%d.%d.%d.%d",
(int)((unsigned char)host->h_addr_list[0][0]),
(int)((unsigned char)host->h_addr_list[0][1]),
(int)((unsigned char)host->h_addr_list[0][2]),
(int)((unsigned char)host->h_addr_list[0][3]));
}
else
return(0);
return (1);
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
#ifdef AMIGAVERSION
void amiga_netexit()
{
CloseLibrary(SocketBase);
}
int amiga_netinit()
{
if (!(SocketBase = OpenLibrary("bsdsocket.library",SOCKETVERSION))) {
printf("Can't open bsdsocket.library V%d!\n",SOCKETVERSION);
return (0);
}
if (SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))),&errno,
SBTM_SETVAL(SBTC_LOGTAGPTR),"Battalion",
TAG_END)) {
printf("Can't set errno-pointer!\n");
CloseLibrary(SocketBase);
return(0);
}
atexit(amiga_netexit);
return (-1);
}
#endif
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
int setUpClient()
{
char hostIP[40];
lastMonsterUpdate = -1;
lastRecvTime = lastNotDeadYetTime = 0;
#ifdef AMIGAVERSION
if (!amiga_netinit())
return (0);
#endif
/************************/
/* Open datagram socket */
/************************/
if ((sockfd = socket(AF_INET, SOCK_DGRAM,0)) < 0)
{
printf("battalion client cannot open datagram socket\n");
return(0);
}
/*****************************/
/* Prepare client to connect */
/*****************************/
bzero((char *) &cli_addr, sizeof(cli_addr));
cli_addr.sin_family = AF_INET;
cli_addr.sin_addr.s_addr = htonl(INADDR_ANY);
cli_addr.sin_port = htons(0);
if (bind(sockfd, (struct sockaddr *) &cli_addr, sizeof(cli_addr)) < 0)
{
printf("battalion client cannot bind local address\n");
return(0);
}
/****************************************************************/
/* Set up data structure to indicate which server to connect to */
/****************************************************************/
if ((hostAddr[0] >= '0') && (hostAddr[0] <= '9'))
{
strcpy (hostIP, hostAddr);
}
else
{
if(!HostnameToIP(hostAddr, hostIP))
{
strcpy (hostIP, hostAddr);
}
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(hostIP);
serv_addr.sin_port = htons(portNumber);
printf("battalion client running - looking for server on %s (%s) on port %d\n\n", hostAddr, hostIP, portNumber);
/*******************/
/* set nonblocking */
/*******************/
#ifndef AMIGAVERSION
fcntl(sockfd,F_SETFL,FNDELAY);
#else
IoctlSocket(sockfd,FIONBIO,(char *)&ioctl_true);
#endif
return(1);
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
int setUpNetwork()
{
int i;
char host[MAXHOSTNAMELEN];
char hostIP[MAXHOSTNAMELEN];
#ifdef AMIGAVERSION
if (!amiga_netinit())
return (0);
#endif
/************************/
/* Open datagram socket */
/************************/
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
printf("Server cannot open datagram socket\n");
return(0);
}
/******************************************************/
/* Set up server to allow connection from any address */
/******************************************************/
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portNumber);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
printf("battalion server cannot bind to local address\n");
return(0);
}
gethostname(host,MAXHOSTNAMELEN);
HostnameToIP(host, hostIP);
printf("battalion server running on %s (%s) on port %d\n\n", host, hostIP, portNumber);
/*******************/
/* set nonblocking */
/*******************/
#ifndef AMIGAVERSION
fcntl(sockfd,F_SETFL,FNDELAY);
#else
IoctlSocket(sockfd,FIONBIO,(char *)&ioctl_true);
#endif
/******************/
/* no clients yet */
/******************/
numClients = 0;
for (i=0; i<MAXCLIENTS;i++)
{
clientsAlive[i] = 0;
lastClientMonsterUpdate[i] = -1;
}
return(1);
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
void updateNetworkBuildings(char * recvline, struct tree * treelist)
{
char command[MAXLINE];
char mesg[MAXLINE];
int buildingNumber;
int i;
struct tree * temptree;
/*****************************************************/
/* find out which building was destroyed by a client */
/*****************************************************/
sscanf(recvline, "%s %d", command, &buildingNumber);
for (temptree = treelist->next; temptree != NULL; temptree = temptree->next)
if (temptree->number == buildingNumber)
temptree->intact = 0;
/***********************************************************************/
/* tell all the clients about the building destroyed by another client */
/***********************************************************************/
sprintf(mesg, "%s %d #", MESG_BUILDING, buildingNumber);
for(i=0; i<numClients; i++)
sendMessage(mesg, &clients[i], sizeof(clients[i]));
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
void addNewNetworkTank(char * recvline, struct tank * tanklist,
void * arena, int sizeTank)
{
char command[MAXLINE];
float x, z;
int type, number;
float finRange, speed;
struct tank * temptank;
int foundIt;
sscanf(recvline, "%s %d %f %f %f %f %d",
command, &number, &x, &z, &finRange, &speed, &type);
foundIt = 0;
for (temptank = tanklist->next; temptank != NULL; temptank = temptank->next)
{
if (number == temptank->number)
foundIt = 1;
}
if (!foundIt)
{
fprintf(stderr, "ADDING A NEW TANK %d %f %f %f %f %d \n", number, x, z, finRange, speed, type);
temptank = (struct tank *) amalloc(sizeTank, arena);
temptank->goforit = NULL;
temptank->number = number;
temptank->x = x + globalxshift;;
temptank->y = -1;
temptank->z = z + globalxshift;;
temptank->xv = 0;
temptank->zv = 0;
temptank->range = 3;
temptank->rad = 0;
temptank->theta = 0;
temptank->count = 0;
temptank->finalR = finRange;
temptank->damage = 1;
temptank->minrange = 0.5;
temptank->speed = speed;
temptank->type = (char) type;
temptank->next = tanklist->next;
tanklist->next = temptank;
}
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
void updateNetworkTank(char * recvline, struct tank * tanklist)
{
char command[MAXLINE];
float x, z;
int number, maserCount;
struct tank * temptank, * foundtank;
int foundIt;
sscanf(recvline, "%s %d %f %f %d",
command, &number, &x, &z, &maserCount);
/* this should have somethin that uses the monsters current location to modify the
* location of the tank
*/
foundIt = 0;
for (temptank = tanklist->next; (temptank != NULL) && (!foundIt); temptank = temptank->next)
{
if (number == temptank->number)
{
foundIt = 1;
foundtank = temptank;
}
}
if (foundIt)
{
/*
fprintf(stderr, "%s \n", recvline);
fprintf(stderr, "UPDATING TANK %d %f %f %f %d \n", number, x, y, z, maserCount);
*/
foundtank->x = x + globalxshift;
foundtank->z = z + globalzshift;
if (maserCount > 1)
foundtank->maserCount = 10;
}
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
void tellAboutAllTanks(struct sockaddr_in * cli, int length
, struct tank * tanklist)
{
char mesg[MAXLINE];
struct tank * tempTank;
for (tempTank = tanklist->next; tempTank != NULL; tempTank = tempTank->next)
{
fprintf(stderr, "sending FULL data on tank %d to a new client\n", tempTank->number);
/* nother copy of this elsewhere */
sprintf(mesg, "%s %d %3.1f %3.1f %3.1f %0.3f %d %d #", MESG_NEW_TANK,
tempTank->number,
tempTank->x-globalxshift,
tempTank->z-globalzshift,
tempTank->finalR,
tempTank->speed,
tempTank->type,
tempTank->maserCount
);
sendMessage(mesg, cli, length);
}
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
void updateNetworkMonsters(char * recvline, long clientFrom, void * arena)
{
struct targetInfo * tempTarget, *thaOne;
float n_energy, n_x, n_z;
int n_frame;
int n_monsterType, n_dead, n_beamOn;
int n_horzrot, n_vertrot, n_timeDead;
int exists;
char command[MAXLINE];
sscanf(recvline, "%s %d %d %f %d %d %d %f %f %d %d",
command,
&n_frame,
&n_monsterType,
&n_energy,
&n_horzrot,
&n_vertrot,
&n_dead,
&n_x,
&n_z,
&n_beamOn,
&n_timeDead
);
exists = 0;
for(tempTarget = targets; tempTarget != NULL; tempTarget=tempTarget->next)
{
if (tempTarget->net_clientFrom == clientFrom)
{
exists = 1;
thaOne = tempTarget;
}
}
if (exists && (thaOne->monster.monster == n_monsterType))
{
/*****************************************************************/
/* update the values in the currently existing networked monster */
/*****************************************************************/
thaOne->net_headHorzRotate = n_horzrot;
thaOne->net_headVertRotate = n_vertrot;
thaOne->net_energyRemaining = n_energy;
thaOne->net_x = n_x + globalxshift;
thaOne->net_z = n_z + globalzshift;
thaOne->net_beamOn = n_beamOn;
}
else if (n_timeDead < 40)
{
/*******************************/
/* add a new networked monster */
/*******************************/
addNetworkTarget(clientFrom, n_monsterType, n_horzrot, n_vertrot,
n_energy, n_x + globalxshift, n_z + globalzshift, n_beamOn, arena);
}
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
void addNetworkTarget(long fromNum, int monsterType, float horz, float vert,
float energy, float x, float z, int beamOn, void * arena)
{
struct monsterInfo newMonster;
struct targetInfo * nother, *temp;
int alreadyExists;
int i;
alreadyExists = 0;
for (i=0, temp=targets->next; temp != NULL; i++,temp=temp->next)
{
if (temp->net_clientFrom == fromNum)
{
alreadyExists = 1;
/******************************/
/* monster type has changed ! */
/******************************/
newMonster.monster = monsterType;
newMonster = resetMonsterParameters(newMonster);
temp->monster = newMonster;
temp->net_clientFrom = fromNum;
temp->net_headHorzRotate = horz;
temp->net_headVertRotate = vert;
temp->net_energyRemaining = energy;
temp->net_x = x;
temp->net_z = z;
temp->net_beamOn = beamOn;
temp->monster.headHorzRotate = horz;
temp->monster.headVertRotate = vert;
temp->x = x;
temp->z = z;
printf("updating a remote monster that has changed its type\n");
}
}
/************************************/
/* add a new monster into this game */
/************************************/
if (!alreadyExists)
{
newMonster.monster = monsterType;
newMonster = resetMonsterParameters(newMonster);
nother = (struct targetInfo *) amalloc(sizeof(struct targetInfo), arena);
if (nother != NULL)
{
nother->monster = newMonster;
nother->net_clientFrom = fromNum;
nother->net_headHorzRotate = horz;
nother->net_headVertRotate = vert;
nother->net_energyRemaining = energy;
nother->net_x = x;
nother->net_z = z;
nother->net_beamOn = beamOn;
nother->monster.headHorzRotate = horz;
nother->monster.headVertRotate = vert;
nother->x = x;
nother->z = z;
nother->next = targets->next;
targets->next = nother;
}
}
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
void updateClientMonster(char * recvline, void * arena)
{
struct targetInfo * tempTarget, *thaOne;
float n_energy, n_x, n_z;
int n_frame;
int n_monsterType, n_dead, n_beamOn;
int n_horzrot, n_vertrot, n_timeDead;
int exists;
long recvfrom;
char command[MAXLINE];
char orig_command[MAXLINE];
sscanf(recvline, "%s %ld %s %d %d %f %d %d %d %f %f %d %d",
command,
&recvfrom,
orig_command,
&n_frame,
&n_monsterType,
&n_energy,
&n_horzrot,
&n_vertrot,
&n_dead,
&n_x,
&n_z,
&n_beamOn,
&n_timeDead
);
exists = 0;
for(tempTarget = targets; tempTarget != NULL; tempTarget=tempTarget->next)
{ /* note difference here ! */
if (tempTarget->net_clientFrom == recvfrom)
{
exists = 1;
thaOne = tempTarget;
}
}
if (exists && (thaOne->monster.monster == n_monsterType))
{
/*****************************************************************/
/* update the values in the currently existing networked monster */
/*****************************************************************/
thaOne->net_headHorzRotate = n_horzrot;
thaOne->net_headVertRotate = n_vertrot;
thaOne->net_energyRemaining = n_energy;
thaOne->net_x = n_x + globalxshift;
thaOne->net_z = n_z + globalzshift;
thaOne->net_beamOn = n_beamOn;
}
else if (n_timeDead < 40)
{
/*******************************/
/* add a new networked monster */
/*******************************/
addNetworkTarget(recvfrom, n_monsterType, n_horzrot, n_vertrot,
n_energy, n_x + globalxshift, n_z + globalzshift, n_beamOn, arena);
}
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
int sendMessage(char * mesg, struct sockaddr_in * cli, int length)
{
int n;
n = strlen(mesg)+1;
if (sendto(sockfd, mesg, n, 0, (struct sockaddr *) cli, length) != n)
{
printf("Sendto error\n");
return(1);
}
else
return(0);
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
void processClient(time_t now, int mainCounter, int totalCounter,
struct tree * treelist, struct tank * tanklist, void * arena,
int sizeTank, struct monsterInfo Googelon,
int buildingBoomThisFrameCounter, int buildingBoomThisFrame[20])
{
char recvline[MAXLINE];
char mesg[MAXLINE];
char command[MAXLINE];
int n;
int servlen;
long clientFrom;
int j;
int frameNum;
extern int errno;
/* send a request every once in a while until connection established */
/* if I haven't seen any data from the server in a while try to reconnect */
/* this may be a bit harsh to say connected = 0 */
if (now > (lastRecvTime + RECONNECT_TIME))
connected = 0;
if (!connected)
{
sprintf(mesg,MESG_REQUEST);
sendMessage(mesg, &serv_addr, sizeof(serv_addr));
}
if (now > (lastNotDeadYetTime + IM_NOT_DEAD_SEND_TIME))
{
lastNotDeadYetTime = now;
sprintf(mesg,MESG_NOTDEADYET);
sendMessage(mesg, &serv_addr, sizeof(serv_addr));
}
/*******************************************************/
/* tell all the clients when a tree has been destroyed */
/*******************************************************/
for(j=0;j<buildingBoomThisFrameCounter;j++)
{
sprintf(mesg, "%s %d #", MESG_BUILDING, buildingBoomThisFrame[j]);
sendMessage(mesg, &serv_addr, sizeof(serv_addr));
}
/***********************************/
/* ocassionally send to the server */
/***********************************/
if (!(mainCounter % MONSTER_UPDATE_RATE))
{
sprintf(mesg, "%s %1d %1d %1.0f %1d %1d %1d %1.1f %1.1f %1d %1d#",
MESG_UPDATE,
totalCounter,
Googelon.monster,
Googelon.energyRemaining,
Googelon.headHorzRotate,
Googelon.headVertRotate,
Googelon.monsterIsDead,
-globalxshift,
-globalzshift,
beamOnSinceLast,
Googelon.timeDead
);
beamOnSinceLast = 0;
sendMessage(mesg, &serv_addr, sizeof(serv_addr));
}
/*************************************/
/* wait for messages from the server */
/*************************************/
servlen = sizeof(serv_addr);
#ifndef AMIGAVERSION
n = recvfrom(sockfd, recvline, MAXLINE, 0, (struct sockaddr *) &serv_addr, (int *)& servlen);
#else
n = recvfrom(sockfd, (UBYTE *)recvline, MAXLINE, 0,
(struct sockaddr *)&serv_addr, (LONG *)&servlen);
#endif
if ((n < 0) && (errno != EWOULDBLOCK))
{
printf("Client receive error\n");
}
else if (n >= 0)
{
clientFrom = ntohl(serv_addr.sin_addr.s_addr);
/*
printf("RECEIVED: %s",recvline);
printf("FROM: %ld\n\n",clientFrom);
*/
connected = 1;
lastRecvTime = now;
sscanf(recvline, "%s %d", command, &frameNum);
if (strcmp(command, MESG_UPDATE) == 0)
{
/*if (frameNum > lastMonsterUpdate) */
/* took this out since there can be > 1 monster being sent
* to the client
*/
{
updateNetworkMonsters(recvline, clientFrom, arena);
lastMonsterUpdate = frameNum;
}
}
if (strcmp(command, MESG_NEW_TANK) == 0)
{
addNewNetworkTank(recvline, tanklist, arena, sizeTank);
}
if (strcmp(command, MESG_UPDATE_TANK) == 0)
{
updateNetworkTank(recvline, tanklist);
}
if (strcmp(command, MESG_BUILDING) == 0)
{
updateNetworkBuildings(recvline, treelist);
}
if (strcmp(command, MESG_CLIENT_CLIENT_UPDATE) == 0)
{
updateClientMonster(recvline, arena);
}
}
/* close(sockfd); */
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
void tellAboutAllDeadBuildings(struct sockaddr_in * cli, int length,
int buildingBoomSoFarCounter,
int buildingBoomSoFar[800])
{
int j;
char mesg[MAXLINE];
for(j=0; j<buildingBoomSoFarCounter; j++)
{
sprintf(mesg, "%s %d #", MESG_BUILDING, buildingBoomSoFar[j]);
sendMessage(mesg, cli, length);
}
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
/* there is now a connected = 0 in setPlayConditions!!! */
void processNetwork(time_t now, int mainCounter, int totalCounter,
struct tree * treelist, struct tank * tanklist, void * arena,
struct monsterInfo Googelon, int buildingBoomSoFarCounter,
int buildingBoomThisFrameCounter, int buildingBoomSoFar[800],
int buildingBoomThisFrame[20])
{
long recvFrom;
struct sockaddr_in cli_addr;
char recvline[MAXLINE];
char mesg[MAXLINE];
char command[MAXLINE];
struct targetInfo * tempTarget;
extern int errno;
int clilen;
int oldClient;
int n;
int i, j;
int gotOne;
int noMore;
int thisClient;
int frameNumber;
clilen = sizeof(cli_addr);
noMore = 0;
tankModulator = (tankModulator + 1) % MONSTER_UPDATE_RATE;
while(!noMore)
{
/**********************/
/* Read incoming data */
/**********************/
#ifndef AMIGAVERSION
n = recvfrom(sockfd, recvline, MAXLINE, 0, (struct sockaddr *) &cli_addr, (int *)& clilen);
#else
n = recvfrom(sockfd, (UBYTE *)recvline, MAXLINE, 0,
(struct sockaddr *)&cli_addr, (LONG *)&clilen);
#endif
if (n < 0)
if(errno != EWOULDBLOCK)
{
printf("Server recvfrom error\n");
noMore = 1;
}
else
{
noMore = 1;
}
else
{
recvFrom = ntohl(cli_addr.sin_addr.s_addr);
/*
printf("RECEIVED: %s",recvline);
printf(" FROM: %ld\n\n",recvFrom);
*/
thisClient = -1;
for(i=0; i<numClients; i++)
if (recvFrom == clientsFrom[i])
{
thisClient = i;
}
/* its possible we are getting an update message from a
client we didn't know we had (if server crashes) so we
ignore all of these messages until it establishes a
'proper' connection */
if (thisClient != -1)
{
if (strcmp(recvline,MESG_NOTDEADYET) == 0)
{
clientsAlive[thisClient] = now;
}
sscanf(recvline, "%s %d", command, &frameNumber);
if (strcmp(command, MESG_UPDATE) == 0)
{
if (frameNumber > lastClientMonsterUpdate[thisClient])
{
updateNetworkMonsters(recvline, recvFrom, arena);
lastClientMonsterUpdate[thisClient] = frameNumber;
/*******************************************/
/* send this info to all the other clients */
/*******************************************/
sprintf(mesg, "%s %ld %s", MESG_CLIENT_CLIENT_UPDATE, recvFrom, recvline);
for(i=0; i<numClients; i++)
if (i != thisClient)
{
sendMessage(mesg, &clients[i], sizeof(clients[i]));
/* fprintf(stderr, "%s\n", mesg); */
}
}
}
}
if (strcmp(command, MESG_BUILDING) == 0)
{
updateNetworkBuildings(recvline, treelist);
}
if (strcmp(recvline,MESG_REQUEST) == 0)
{
/*********************************************/
/* need to see if this client already exists */
/*********************************************/
oldClient = 0;
for(i=0; i<numClients; i++)
{
if (recvFrom == clientsFrom[i])
{
clients[i] = cli_addr;
clientsAlive[i] = now;
oldClient = 1;
}
}
if (oldClient)
{
sprintf(mesg,MESG_REAQUIRE);
sendMessage(mesg, &cli_addr, clilen);
tellAboutAllDeadBuildings(&cli_addr, clilen, buildingBoomSoFarCounter, buildingBoomSoFar);
tellAboutAllTanks(&cli_addr, clilen, tanklist);
}
if (!oldClient)
{
clients[numClients] = cli_addr;
clientsFrom[numClients] = recvFrom;
clientsAlive[numClients] = now;
numClients++;
sprintf(mesg, MESG_ACKNOWLEDGE);
sendMessage(mesg, &cli_addr, clilen);
tellAboutAllDeadBuildings(&cli_addr, clilen, buildingBoomSoFarCounter, buildingBoomSoFar);
tellAboutAllTanks(&cli_addr, clilen, tanklist);
}
}
}
}
/****************************************************************/
/* kill any client connection that has not responded in a while */
/****************************************************************/
i = 0;
gotOne = 0;
while ((i < numClients) && (!gotOne))
{
if ((clientsAlive[i]+IM_NOT_DEAD_YET_TIME) < now)
{
printf("killing client %d\n", i);
/* remove the appropriate target */
for(tempTarget = targets; tempTarget != NULL; tempTarget=tempTarget->next)
{
if (tempTarget->net_clientFrom == clientsFrom[i])
tempTarget->net_energyRemaining = 0;
}
for (j=i+1; j < numClients; j++)
{
clients[j-1] = clients[j];
clientsFrom[j-1] = clientsFrom[j];
clientsAlive[j-1] = clientsAlive[j];
gotOne = 1;
}
numClients -= 1;
}
else
i++;
}
/*******************************************************/
/* tell all the clients when a tree has been destroyed */
/*******************************************************/
for(j=0;j<buildingBoomThisFrameCounter;j++)
{
sprintf(mesg, "%s %d #", MESG_BUILDING, buildingBoomThisFrame[j]);
for(i=0; i<numClients; i++)
sendMessage(mesg, &clients[i], sizeof(clients[i]));
}
/*************************************************************/
/* ocassionally broadcast to all currently connected clients */
/*************************************************************/
if (!(mainCounter % MONSTER_UPDATE_RATE))
{
sprintf(mesg, "%s %1d %1d %1.0f %1d %1d %1d %1.1f %1.1f %1d %1d#",
MESG_UPDATE,
totalCounter,
Googelon.monster,
Googelon.energyRemaining,
Googelon.headHorzRotate,
Googelon.headVertRotate,
Googelon.monsterIsDead,
-globalxshift,
-globalzshift,
beamOnSinceLast,
Googelon.timeDead
);
beamOnSinceLast = 0;
for(i=0;i<numClients;i++)
sendMessage(mesg, &clients[i], sizeof(clients[i]));
}
}